package com.sy.controller;

import com.sy.entity.User;
import com.sy.utils.CommonUtils;
import com.sy.utils.RandomUtils;
import com.sy.utils.RedisOperations;
import com.sy.vo.CustomerInfo;
import com.sy.vo.LoginVo;
import com.sy.vo.RegistVo;
import com.sy.vo.UpdateUserVo;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.Objects;

import static com.sy.constant.BusinessConstant.*;

@RestController
public class UserController extends BaseController {

    @Autowired
    private RedisOperations redisOperations;

    /**
     * 属性描述: 响应对象
     */
    @Autowired(required = false)
    private HttpServletResponse res;
    @Autowired
    private HttpServletRequest req;

    @RequestMapping(value = "users/validateCode", method = RequestMethod.GET)
    public void sendValidateCode(String phone) {
        //获取要发送短信的手机号码
//        String phone = getParameter("phone", String.class);
        userService.sendValidateCode(phone);
    }

    @RequestMapping(value = "users/validateCode", method = RequestMethod.POST)
    public void submitCustomerInfo(@RequestBody CustomerInfo customerInfo) {
        //提交顾客信息
        userService.submitCustomerInfo(customerInfo);
    }

    @RequestMapping(value = "users/regist", method = RequestMethod.POST)
    public void regist(@RequestBody RegistVo registVo) {
        //获取注册操作是前端传递的参数
//        RegistVo registVo = parameters2Bean(RegistVo.class);
        userService.regist(registVo);
    }

    @RequestMapping(value = "users/login", method = RequestMethod.POST)
    public User login(@RequestBody LoginVo loginVo, @CookieValue(value = COOKIE_USER_TOKEN_NAME, defaultValue = DEFAULT_COOKIE_NAME) String token) {
        User user = userService.login(loginVo);
        //保留用户的登录状态
        //1.使用Session保存会话的问题：
        //随着服务器的重启，Session会被销毁，因为Session中的具体数据是保存在服务器对应的内存空间中的
        //解决：将会话状态保存在独立于Tomcat服务器以外的地方，这样服务器重启数据也不会丢失
        //参考方案：MySQL(如果用户量过大，并发数过多，读写效率低下)、Redis
        //2.使用Redis保存会话状态的时候
        //key-可以唯一区分当前客户端是哪一个客户端，这里不能使用SessionId作为标识，因为服务器重启会导致
        //旧的SessionId无效，服务器端重写写回一个新的SessionId到Cookie中，所以为了解决这个问题，可以
        //在Cookie中自己生成一个当前客户端的唯一标识，Redis中用户登录状态对应的key设计成"user:唯一标识"的形式
        //value-hash类型，其中的属性就是User类型中的属性名
        //具体实现：
        //(1)获取Cookie中用于保存当前客户端唯一标识的数据
//        String token = getCookie(COOKIE_USER_TOKEN_NAME);
        //(a)如果有就不用重新生成
        //(b)如果没有则需要重新生成
        if (StringUtils.isBlank(token) || StringUtils.equals(DEFAULT_COOKIE_NAME, token)) {
            //生成token
            token = RandomUtils.getUuid();
            //写入浏览器
            Cookie cookie = new Cookie(COOKIE_USER_TOKEN_NAME, token);
            cookie.setPath(COOKIE_ROOT_PATH);
            cookie.setMaxAge(USER_SESSION_MAX_AGE);
            //将登录的用户对象写入Redis中
            res.addCookie(cookie);
            Map<String, String> userMap = CommonUtils.bean2Map(user);
            userMap.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
            String redisUserKey = REDIS_USER_KEY_PREFIX + token;
            redisOperations.hmset(redisUserKey, userMap);
            redisOperations.expire(redisUserKey, USER_SESSION_MAX_AGE);
        }

        return user;
    }


    @RequestMapping(value = "users/loginUser", method = RequestMethod.GET)
    public User getLoginUser() {
        String token = null;
        Cookie[] cookies = req.getCookies();
        if (!ArrayUtils.isEmpty(cookies)) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(COOKIE_USER_TOKEN_NAME)) {
                    token = cookie.getValue();
                }
            }
        }
        if (StringUtils.isNotBlank(token)) {
            String redisUserKey = REDIS_USER_KEY_PREFIX + token;
            if (redisOperations.exists(redisUserKey)) {
                Map<String, String> redisUserMap = redisOperations.hgetall(redisUserKey);
                User user = CommonUtils.map2Bean(redisUserMap, User.class);
                if (Objects.isNull(user)) {
                    return null;
                } else {
                    return user;
                }
            }
        }
        return null;

    }

    @RequestMapping(value = "users/logout", method = RequestMethod.DELETE)
    public boolean logout(@CookieValue(COOKIE_USER_TOKEN_NAME) String token) {
        //或者Cookie中的token
//        String token = getCookie(COOKIE_USER_TOKEN_NAME);
        if (StringUtils.isNotBlank(token)) {
            //删除Cookie
            Cookie[] cookies = req.getCookies();
            if (!Objects.isNull(cookies)) {
                for (Cookie cookie : cookies) {
                    if (cookie.getName().equals(COOKIE_USER_TOKEN_NAME)) {
                        cookie.setPath(COOKIE_ROOT_PATH);
                        cookie.setMaxAge(COOKIE_MIN_AGE);
                        res.addCookie(cookie);
                    }
                }
            }
            //删除Redis中对应key
            String redisUserKey = REDIS_USER_KEY_PREFIX + token;
            return redisOperations.del(redisUserKey);
        }
        return false;
    }

    @RequestMapping(value = "users", method = RequestMethod.PUT)
    public void updateUserInfo(@RequestBody UpdateUserVo updateUserVo, @CookieValue(value = COOKIE_USER_TOKEN_NAME) String token) {
            userService.updateUserInfoByConditions(updateUserVo, token);
    }
}
